/**
 * 多模型路由器
 * 负责模型选择、负载均衡和故障转移
 */

import { BaseModelAdapter, ModelType, MODEL_CAPABILITIES } from './base-model-adapter';
import { OpenAIAdapter } from './openai-adapter';
import { ClaudeAdapter } from './claude-adapter';

export interface ModelSelectionCriteria {
  taskType?: 'creative' | 'technical' | 'analysis' | 'general' | 'chinese';
  language?: 'en' | 'zh' | 'ja' | 'ko';
  maxCost?: number;
  maxLatency?: number;
  preferredProvider?: string;
}

export interface ModelHealth {
  modelType: ModelType;
  isHealthy: boolean;
  lastCheck: Date;
  responseTime: number;
  errorRate: number;
}

export class ModelRouter {
  private adapters: Map<ModelType, BaseModelAdapter> = new Map();
  private healthStatus: Map<ModelType, ModelHealth> = new Map();
  private fallbackChain: ModelType[][] = [];

  constructor() {
    this.initializeFallbackChain();
    this.startHealthMonitoring();
  }

  /**
   * 注册模型适配器
   */
  registerAdapter(modelType: ModelType, adapter: BaseModelAdapter) {
    this.adapters.set(modelType, adapter);
    this.healthStatus.set(modelType, {
      modelType,
      isHealthy: true,
      lastCheck: new Date(),
      responseTime: 0,
      errorRate: 0
    });
  }

  /**
   * 根据条件选择最佳模型
   */
  selectModel(criteria: ModelSelectionCriteria = {}): ModelType | null {
    const availableModels = this.getHealthyModels();
    
    if (availableModels.length === 0) {
      return null;
    }

    // 根据任务类型筛选
    let candidates = availableModels;
    
    if (criteria.taskType) {
      candidates = candidates.filter(model => {
        const capabilities = MODEL_CAPABILITIES[model];
        return capabilities.specialties.includes(criteria.taskType!);
      });
    }

    // 根据语言筛选
    if (criteria.language) {
      candidates = candidates.filter(model => {
        const capabilities = MODEL_CAPABILITIES[model];
        return capabilities.languages.includes(criteria.language!);
      });
    }

    // 根据成本筛选
    if (criteria.maxCost) {
      candidates = candidates.filter(model => {
        const capabilities = MODEL_CAPABILITIES[model];
        return capabilities.costPer1kTokens <= criteria.maxCost!;
      });
    }

    // 根据提供商筛选
    if (criteria.preferredProvider) {
      const preferred = candidates.filter(model => {
        const capabilities = MODEL_CAPABILITIES[model];
        return capabilities.provider === criteria.preferredProvider;
      });
      if (preferred.length > 0) {
        candidates = preferred;
      }
    }

    if (candidates.length === 0) {
      // 如果没有符合条件的模型，返回最健康的模型
      return availableModels[0];
    }

    // 选择成本最低的模型
    return candidates.reduce((best, current) => {
      const bestCost = MODEL_CAPABILITIES[best].costPer1kTokens;
      const currentCost = MODEL_CAPABILITIES[current].costPer1kTokens;
      return currentCost < bestCost ? current : best;
    });
  }

  /**
   * 获取模型适配器
   */
  getAdapter(modelType: ModelType): BaseModelAdapter | null {
    return this.adapters.get(modelType) || null;
  }

  /**
   * 获取健康的模型列表
   */
  private getHealthyModels(): ModelType[] {
    return Array.from(this.healthStatus.entries())
      .filter(([_, health]) => health.isHealthy)
      .map(([modelType, _]) => modelType)
      .sort((a, b) => {
        const healthA = this.healthStatus.get(a)!;
        const healthB = this.healthStatus.get(b)!;
        // 按响应时间和错误率排序
        const scoreA = healthA.responseTime + healthA.errorRate * 1000;
        const scoreB = healthB.responseTime + healthB.errorRate * 1000;
        return scoreA - scoreB;
      });
  }

  /**
   * 初始化故障转移链
   */
  private initializeFallbackChain() {
    this.fallbackChain = [
      // 创意写作链
      [ModelType.GPT4, ModelType.CLAUDE, ModelType.QWEN],
      // 技术分析链
      [ModelType.CLAUDE, ModelType.GPT4, ModelType.DEEPSEEK],
      // 中文处理链
      [ModelType.QWEN, ModelType.WENXIN, ModelType.GPT4],
      // 通用处理链
      [ModelType.GPT35, ModelType.QWEN, ModelType.WENXIN]
    ];
  }

  /**
   * 获取故障转移模型
   */
  getFallbackModel(failedModel: ModelType, taskType?: string): ModelType | null {
    let chain = this.fallbackChain[0]; // 默认链

    // 根据任务类型选择故障转移链
    if (taskType === 'creative') {
      chain = this.fallbackChain[0];
    } else if (taskType === 'technical') {
      chain = this.fallbackChain[1];
    } else if (taskType === 'chinese') {
      chain = this.fallbackChain[2];
    } else {
      chain = this.fallbackChain[3];
    }

    // 找到失败模型在链中的位置，返回下一个健康的模型
    const failedIndex = chain.indexOf(failedModel);
    if (failedIndex === -1) {
      return this.getHealthyModels()[0] || null;
    }

    for (let i = failedIndex + 1; i < chain.length; i++) {
      const candidate = chain[i];
      const health = this.healthStatus.get(candidate);
      if (health?.isHealthy && this.adapters.has(candidate)) {
        return candidate;
      }
    }

    return null;
  }

  /**
   * 启动健康监控
   */
  private startHealthMonitoring() {
    setInterval(async () => {
      for (const [modelType, adapter] of this.adapters) {
        try {
          const startTime = Date.now();
          const isHealthy = await adapter.healthCheck();
          const responseTime = Date.now() - startTime;

          const health = this.healthStatus.get(modelType)!;
          health.isHealthy = isHealthy;
          health.lastCheck = new Date();
          health.responseTime = responseTime;
          
          // 更新错误率（简单的指数移动平均）
          if (!isHealthy) {
            health.errorRate = health.errorRate * 0.9 + 0.1;
          } else {
            health.errorRate = health.errorRate * 0.95;
          }
        } catch (error) {
          console.error(`Health check failed for ${modelType}:`, error);
          const health = this.healthStatus.get(modelType)!;
          health.isHealthy = false;
          health.lastCheck = new Date();
          health.errorRate = Math.min(health.errorRate + 0.1, 1.0);
        }
      }
    }, 60000); // 每分钟检查一次
  }

  /**
   * 获取所有模型的健康状态
   */
  getHealthStatus(): ModelHealth[] {
    return Array.from(this.healthStatus.values());
  }

  /**
   * 获取模型统计信息
   */
  getModelStats() {
    const stats = {
      totalModels: this.adapters.size,
      healthyModels: this.getHealthyModels().length,
      modelHealth: this.getHealthStatus(),
      capabilities: MODEL_CAPABILITIES
    };

    return stats;
  }
}
